package xml;

import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import toolkit.Debug;

public class DataListParser
{
	public List<Map<String, Object>> getDataListFrom(String location)
	{
		try
		{
			URL url = new URL(location);
			InputStream is = url.openStream();
			
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document doc = db.parse(is);
			
			Element root = doc.getDocumentElement();
			
			if (root != null)
			{
				root.normalize();
				
				Debug.log("Root element = " + root.getNodeName());
				
				return getDataList(root);
			}
		}
		catch (Exception e)
		{
			Debug.log(e);
		}
		
		return null;
	}
	
	// Recursive method
	public List<Map<String, Object>> getDataList(Element container)
	{
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		
		for (Element element: getElementChildren(container))
		{
			list.add(getDataElement(element));
		}
		
		return list;
	}
	
	public Map<String, Object> getDataElement(Element element)
	{
		Map<String, Object> data = new HashMap<String, Object>();
		
		for (Element attribute: getElementChildren(element))
		{
			String key = attribute.getTagName();
			
			if (isData(attribute))
			{
				data.put(key, attribute.getTextContent());
			}
			else if (isDataList(attribute))
			{
				data.put(key, getDataList(attribute));
			}
		}
		
		return data;
	}
	
	public boolean isDataList(Element element)
	{
		return hasElementChildren(getFirstElementChild(element));
	}
	
	public boolean isData(Element element)
	{
		NodeList list = element.getChildNodes();
		
		return list.getLength() == 1 && list.item(0).getNodeType() == Node.TEXT_NODE;
	}
	
	public boolean hasElementChildren(Element parent)
	{
		return parent != null && getFirstElementChild(parent) != null;
	}
	
	public List<Element> getElementChildren(Element parent)
	{
		List<Element> elements = new ArrayList<Element>();
		
		if (parent != null)
		{
			NodeList nodes = parent.getChildNodes();
			
			for (int i = 0, length = nodes.getLength(); i < length; i++)
			{
				Node node = nodes.item(i);
				
				if (node.getNodeType() == Node.ELEMENT_NODE)
				{
					elements.add((Element) node);
				}
			}
		}
		
		return elements;
	}
	
	public Element getFirstElementChild(Element parent)
	{
		if (parent != null)
		{
			NodeList nodes = parent.getChildNodes();
			
			for (int i = 0, length = nodes.getLength(); i < length; i++)
			{
				Node node = nodes.item(i);
				
				if (node.getNodeType() == Node.ELEMENT_NODE)
				{
					return (Element) node;
				}
			}
		}
		
		return null;
	}
}
